package study.cell_game.utils;

import java.util.ArrayList;
import java.util.List;

import org.andengine.entity.sprite.Sprite;

import study.cell_game.activity.GameActivity;
import study.cell_game.enums.Direction;
import study.cell_game.enums.InterfaceActionMode;
import study.cell_game.enums.PlayerColor;
import study.cell_game.objects.ArrowSprite;
import study.cell_game.objects.Cell;
import study.cell_game.objects.CellSprite;
import study.cell_game.objects.Player;
import study.cell_game.objects.textures.TokenTextures;
import study.cell_game.objects.tokens.Token;
import study.cell_game.objects.tokens.TokenSprite;
import study.cell_game.scenes.GameScene;

public class TapManager {
	protected TapManager() {
	}

	private static TapManager instance;

	public static TapManager getInstance() {
		if (instance == null) {
			instance = new TapManager();
		}
		return instance;
	}

	protected TokenSprite tappedToken;
	protected Cell tappedCell;
	
	//protected ITouchArea second;
	protected InterfaceActionMode currentMode = InterfaceActionMode.NONE;

	private void dropToken(){
		currentMode = InterfaceActionMode.NONE;
		tappedToken = null;
	}
	
	private void takeToken(TokenSprite tsprite){
	   if( tsprite.getParentToken().getOwner() == PlayerColor.BLUE)
	   {
		tappedToken = tsprite;
		if(tappedToken.getParentToken().getUsable()){
			currentMode = InterfaceActionMode.PLAY_TOKEN;
		} else {
			currentMode = InterfaceActionMode.PLACE_TOKEN;
			for (Cell cell : Player.getInstance().getAvailableCells()) {
				cell.getSprite().attachChild(
						new Sprite(0, 0, 
								TokenTextures.getInstance().getFullRing(), 
								GameActivity.main.getVertexBufferObjectManager())
					);
			}
			
		}
	   }
	}
	
	List<ArrowSprite> arrowSprites = new ArrayList<ArrowSprite>();
	List<Integer> neighbourIds = new ArrayList<Integer>();
	Sprite rotateSprite;
	
	private void connectToken(TokenSprite token) {
		Token t = token.getParentToken();
		if(t.getOwner() == PlayerColor.BLUE)
		{
		List<Direction> dirs = t.getCell().getOutboundDirections();
		if(dirs.isEmpty()){
			dropToken();
		} else {
			this.currentMode = InterfaceActionMode.MAKE_CONNECTIONS;
			tappedToken = token;
			for(Direction d : dirs){
				//renderowanie strzałek
				ArrowSprite arrowSprite = new ArrowSprite(0, 0, 
						TokenTextures.getInstance().getBlueArrow(), 
						GameActivity.main.getVertexBufferObjectManager(), d);
				arrowSprites.add(arrowSprite);
				//super zawiłe wyciąganie id tokena sąsiada
				neighbourIds.add(t.getCell().getNeighbours()[d.getValue()].getToken().getId());
				
				if(d.equals(t.getPreferredDirection())){
					arrowSprite.setAlpha(1.0f);
					arrowSprite.setScale(1.15f);
				} else {
					arrowSprite.setAlpha(0.4f);
					arrowSprite.setScale(1.0f);
				}
				
				float x = t.getPlayerColor().getX();
				float y = t.getPlayerColor().getY();
				
				switch(d){
				case NORTH:
					arrowSprite.setX(x + 28);
					arrowSprite.setY(y - 15);
					arrowSprite.setRotation(0);
					break;	
				case SOUTH:
					arrowSprite.setX(x + 28);
					arrowSprite.setY(y + 50);
					arrowSprite.setRotation(180);
					break;	
				case NORTHEAST:
					arrowSprite.setX(x + 57);
					arrowSprite.setY(y + 5);
					arrowSprite.setRotation(60);
					break;
				case NORTHWEST: 
					arrowSprite.setX(x - 3);
					arrowSprite.setY(y + 5);
					arrowSprite.setRotation(300);
					break;
				case SOUTHEAST:
					arrowSprite.setX(x + 57);
					arrowSprite.setY(y + 38);
					arrowSprite.setRotation(120);
					break;
				case SOUTHWEST:
					arrowSprite.setX(x - 3);
					arrowSprite.setY(y + 38);
					arrowSprite.setRotation(240);
					break;
				}
				GameScene.getInstance().getOverlayLayer().attachChild(arrowSprite);
				//t.getPlayerColor().attachChild(arrowSprite);
			}
		}
		}
	}
	
	private void playToken(TokenSprite onToken){
		// logika zagrywania żetonu
		//if(tappedToken.getParentToken().
		tappedToken.detachSelf();
		Cell cell = tappedToken.getParentToken().getCell();
		cell.setToken(tappedToken.getParentToken());
		cell.getToken().setCell(cell);
		Player.getInstance().getHand().deleteTokenFromHand(tappedToken.getParentToken().getId());// getHand().deleteTokenFromHand(parent.getId());
		// Player.getInstance().
		tappedToken.getParentToken().setPlaced(true);
		GameScene.getInstance().unregisterTouchArea(tappedToken.getParentToken().getPlayerColor());
		dropToken();
		
		tappedToken = onToken;
		enableRotate();
		
	}
	
	private void rotateToken() {
		tappedToken.getParentToken().rotateClockwise();
		// TODO Auto-generated method stub
		//logika obracania żetonu
	}
	
	private boolean placeToken(Cell cell) {
		if (Player.getInstance().getAvailableCells().contains(cell)) {
			for (Cell c : Player.getInstance().getAvailableCells()) {
				c.getSprite().detachChildren();
			}
			
			//if(parent.getUsable()==false)
			//{
			//this.setX(Map.getCell(i).getX());
			//this.setY(Map.getCell(i).getY());
			// parent.setCell(Map.getCell(i));
			tappedToken.setX(cell.getX());
			tappedToken.setY(cell.getY());
			
			cell.setToken(tappedToken.getParentToken());
			cell.getToken().setCell(cell);
			Player.getInstance().placeToken(tappedToken.getParentToken().getId());// getHand().deleteTokenFromHand(parent.getId());
			// Player.getInstance().
			tappedToken.getParentToken().setPlaced(true);
			GameScene.getInstance().unregisterTouchArea(tappedToken.getParentToken().getPlayerColor());
			return true;
		}
		return false;
	}
	
	public void tapToken(TokenSprite token){
		if(tappedToken != null){
			switch(currentMode){
				case PLACE_TOKEN:
					if(tappedToken.getParentToken().getId() != token.getParentToken().getId()){
						dropToken();
					}
					break;
				case PLAY_TOKEN:
					if(tappedToken.getParentToken().getId() == token.getParentToken().getId()){
						dropToken();
					} else if(token.getParentToken().getPlaced()){
						playToken(token);
						
					} else {
						dropToken();
					}
					break;
				case ROTATE_TOKEN:
					if(tappedToken.getParentToken().getId() == token.getParentToken().getId()){
						rotateToken();
					} else {
						dropToken();
						rotateSprite.detachSelf();
						rotateSprite = null;
					}
					break;
				case MAKE_CONNECTIONS:
					
					if(neighbourIds.contains(token.getParentToken().getId())){
						// tworzym połączenie
						for(ArrowSprite arrowSprite : arrowSprites){
							if(arrowSprite.getDir().equals(tappedToken.getParentToken().getPreferredDirection())){
								arrowSprite.setAlpha(0.4f);
								arrowSprite.setScale(1.0f);
								if(tappedToken.getParentToken().getId() == token.getParentToken().getId()){
									for(Sprite s : arrowSprites){
										s.detachSelf();
									}
									arrowSprites.clear();
									neighbourIds.clear();
									dropToken();
								}
							}
						}
						
						int index = neighbourIds.indexOf(token.getParentToken().getId());
						ArrowSprite arrowSprite = arrowSprites.get(index);
						arrowSprite.setAlpha(1f);
						arrowSprite.setScale(1.15f);
						
						tappedToken.getParentToken().setPreferredDirection(arrowSprite.getDir());
						
					} else {
						for(Sprite s : arrowSprites){
							s.detachSelf();
						}
						arrowSprites.clear();
						neighbourIds.clear();
						dropToken();
					}
			}
			
		} else {
			if(token.getParentToken().getPlaced()){
				connectToken(token);
			} else {
				takeToken(token);
			}
		}
	}
	

	private void enableRotate() {
		currentMode = InterfaceActionMode.ROTATE_TOKEN;
		float x = tappedToken.getX();
		float y = tappedToken.getY(); 
		
		rotateSprite = new Sprite(x + 10,y + 5,
						TokenTextures.getInstance().getRotateArrow(), 
						GameActivity.main.getVertexBufferObjectManager());
		GameScene.getInstance().getOverlayLayer().attachChild(rotateSprite);
	}

	public void tapCell(CellSprite cellSprite) {
		//tapnięcie pola ma sens tylko, gdy mamy token w łapce. w innym wypadku można tapać do woli.
				if(tappedToken != null){
					switch(currentMode){
						case PLACE_TOKEN:
							if(cellSprite.getCell().getToken() == null){
								if(placeToken(cellSprite.getCell())){
									enableRotate();
								}
								
							} // tu będzie else na ewolucję tokenu
							
							break;
						case PLAY_TOKEN:
							dropToken();

							break;
						case ROTATE_TOKEN:
							dropToken();
							rotateSprite.detachSelf();
							rotateSprite = null;
							break;
					}
					
				} 
			}

	
}
